﻿using System;
using System.Collections.Generic;
using System.Linq;
using Atmk.WaterMeter.MIS.Commons;
using Atmk.WaterMeter.MIS.Commons.Interfaces;
using Atmk.WaterMeter.MIS.Commons.Interfaces.Logic;
using Atmk.WaterMeter.MIS.Commons.Interfaces.Repository;
using Atmk.WaterMeter.MIS.Commons.Utils;
using Atmk.WaterMeter.MIS.Commons.ViewModels.Area;
using Atmk.WaterMeter.MIS.Commons.ViewModels.Result;
using Atmk.WaterMeter.MIS.Entities;
using Atmk.WaterMeter.MIS.Entities.Enums;
using Atmk.WaterMeter.MIS.Entities.Models;
using Newtonsoft.Json;

namespace Atmk.WaterMeter.MIS.Logic
{
    public class UserCenterLogic : IUserCenterLogic
    {
        private static readonly NLog.Logger _logger = NLog.LogManager.GetCurrentClassLogger();

        private readonly IRepository _repository;
        private readonly IDistrictRepository _districtRepository;
        private readonly IStaffRepository _staffRepository;
        private readonly IRolesRepository _rolesRepository;
        private readonly IMapRepository _mapRepository;
        private readonly IAreaRepository _areaRepository;

        public UserCenterLogic(
            IRepository repository,
            IDistrictRepository districtRepository,
            IStaffRepository staffRepository,
            IRolesRepository rolesRepository,
            IMapRepository mapRepository,
            IAreaRepository areaRepository
        )
        {
            _repository = repository;
            _districtRepository = districtRepository;
            _staffRepository = staffRepository;
            _rolesRepository = rolesRepository;
            _mapRepository = mapRepository;
            _areaRepository = areaRepository;
        }

        /// <summary>
        /// 获取用户及角色权限信息
        /// </summary>
        /// <param name="staffId"></param>
        /// <returns></returns>
        public IData UserInfo(string staffId)
        {
            var uid = staffId;
            var name = "";
            var role = new List<string>();
            var authority = new List<object>();
            var projectId = "";
            try
            {
                //根据用户名，获取用户类信息

                using (var _context = new atmk_wmdb_devContext())
                {
                    var staff = _context.User.Find(uid);
                    name = staff.Name;
                    projectId = staff.SiteId;
                    //获取角色类
                    var roleEntity = _rolesRepository.GetRoleByUser(uid);
                    role.AddRange(roleEntity.Select(r => r.Name).ToList());

                    authority.AddRange(roleEntity.Select(r =>
                        !string.IsNullOrEmpty(r.Parmissions)
                            ? JsonConvert.DeserializeObject(r.Parmissions)
                            : new List<object>()).ToArray());
                }

            }
            catch (Exception e)
            {
                _logger.Error(e);
            }
            //返回用户信息
            return new UserInfoData
            {
                role = role.ToArray(),
                authority = authority.ToArray(),
                name = name,
                projectId = projectId
            };
        }
        /*  ---注释区域获取，可能更换位置或删除该方法
        /// <summary>
        /// 根据token获取区域信息
        /// </summary>
        /// <param name="staffId"></param>
        /// <returns></returns>
        public  List<string> DistrictCodeList(string staffId)
        {
            try
            {
                var guid = new Guid(userPayload.payload.id);
                //根据用户名，获取用户类信息
                var staff = _staffRepository.FindById(guid);
                var user = (Staff) staff;
                var district = DistrictByUser(user);
                //返回区域信息
                return district.Select(d => d.Id.ToString()).ToList();
            }
            catch (Exception e)
            {
                _logger.Error(e);
                throw new Exception($"DistrictCodeList Error:{e.Message}");
            }
        }

        /// <summary>
        /// 根据用户获取区域信息集合
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public  List<DistrictEntity> DistrictByUser(Staff user)
        {
            //获取片区类
            var district = _districtRepository.FindAll<DistrictEntity>()
                .Where(d => user.DistrictId.Split(',').Contains(d.Id.ToString()));
            return district.ToList();
        }*/

        /// <summary>
        /// 查询所有站点信息及用户信息
        /// </summary>
        /// <returns></returns>
        public AreaOperatorData SelectUserSite(string staffId, string siteid = "")
        {
            try
            {        
                //获取项目集合
                var siteList = SelectAreas(staffId,siteid);
                //获取项目集合下的用户信息
                var staffEntities = _staffRepository.FindAllAsNoTracking<User>()
                    .Where(s => siteList.Select(a=>a.id).Contains(s.SiteId)).ToList();
                var operatorList = new List<Operator>();
                foreach (var staff in staffEntities)
                {
                    var siteName = "";
                    var staff1 = staff;
                    siteName = siteList.First(s => s.id == staff1.SiteId).siteName;
                    var roleEntity = _rolesRepository.GetRoleById(staff.RoleId);
                    operatorList.Add(new Operator
                    {
                        id = staff.Id.ToString(),
                        operatorName = staff.Name, //登陆名
                        surname = staff.Surname, //姓名
                        roleId = staff.RoleId,
                        role = roleEntity.Name, //角色
                        mobile = staff.Mobile, //电话号
                        siteId = staff.SiteId,
                        siteName = siteName, //站点名称
                        pageLines = staff.PageLines,
                        district = staff.DistrictId?.Split(',') ?? new string[0],
                        status = staff.RecordState == (int)RecordStateEnum.Normal ? "正常" : "锁定", //操作员状态
                        createTime = staff.CreateTime.ToString("yyyy-MM-dd HH:mm:ss") //创建时间
                    });
                }
                return new AreaOperatorData
                {
                    siteList = siteList.ToList(),
                    operatorList = operatorList.ToList()
                };
            }
            catch (Exception e)
            {
                _logger.Error(e);
                return new AreaOperatorData
                {
                    siteList = new List<Area>(),
                    operatorList=new List<Operator>()
                };
            }
        }

        /// <summary>
        /// 判断是否超级管理员
        /// </summary>
        /// <param name="uid"></param>
        /// <returns></returns>
        public bool SuperAdmin(string uid)
        {
            var roles = _rolesRepository.GetRoleByUser(uid);
            return roles.Any(r => r.Name == "超级管理员");
        }

        #region 站点

        /// <inheritdoc />
        public List<Area> SelectAreas(string staffId,string siteid)
        {
            //判断是否超级管理员，是获取所有站点，否获取该站数据
            var areaEntities = SuperAdmin(staffId)&&siteid==""
                ? _areaRepository.FindAllAsNoTracking<Project>().ToList()
                : new List<Project>{_areaRepository.GetAreaEntities(siteid)};
            var siteList = new List<Area>();

             List<MapParameter> mapParameters= _mapRepository.CoordinatePoint_mxh(CoordinateType.Project);

            foreach (var t in areaEntities)
            {
                var id = t.Id.ToString();
                //获取坐标类
               var mapParameter= mapParameters.FirstOrDefault(m=>m.NodeId==id);
                siteList.Add(new Area
                {
                    id = id,
                    siteName = t.Name,
                    siteAddress = t.Address,
                    remark = t.Memo,
                    longitude = mapParameter==null? 0: mapParameter.Longitude, //经度 double类型
                    latitude = mapParameter == null ? 0 : mapParameter.Latitude, //纬度 double类型
                    elevation = mapParameter == null ? 0 : mapParameter.Elevation //高程(海拔)  double类型
                });
            }
            return siteList;
        }

        /// <summary>
        /// 添加站点信息
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="message"></param>
        /// <param name="siteId"></param>
        /// <returns></returns>
        public bool AddSite(dynamic obj, out string message, out string siteId)
        {
            message = "";
            siteId = "";
            try
            {
                var site = new Project()
                {
                    Address = obj.siteAddress.ToString(),
                    Memo = obj.remark.ToString()
                };
                siteId = site.Id.ToString();
                var longitude = Simple.DoubleConvertString(obj.longitude.ToString());
                var latitude = Simple.DoubleConvertString(obj.latitude.ToString());
                var elevation = Simple.DoubleConvertString(obj.elevation.ToString());
                if (Enumerable.Count<Project>(_repository.FindAll<Project>(),
                        s => s.Name == site.Name) > 0)
                {
                    message = "站点名称重复";
                    _logger.Warn(message);
                    return false;
                }
                var run = _mapRepository.Edit(site.Id.ToString(), CoordinateType.Project, longitude, latitude,
                    elevation);
                run += _repository.Add(site);
                if (run >= 2)
                    return true;
                message = "添加站点信息失败";
                return false;
            }
            catch (Exception e)
            {
                _logger.Error(e);
                message = e.Message;
                return false;
            }
        }

        /// <summary>
        /// 修改站点信息
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="exception"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public bool UpdateSite(dynamic obj, out string message)
        {
            message = "";
            try
            {
                var sites = Enumerable.Where<Project>(_repository.FindAll<Project>(),
                    i => i.Id.ToString() == obj.id.ToString()).ToList();
                if (!sites.Any())
                {
                    message = "站点不存在，无法修改";
                    return false;
                }
                var site = sites.First();
                site.Name = obj.siteName.ToString();
                site.Address = obj.siteAddress.ToString();
                site.Memo = obj.remark.ToString();
                if (Enumerable.Where<Project>(_repository.FindAll<Project>(),
                        i => i.Id.ToString() != site.Id.ToString()).Count(s => s.Name == site.Name) > 0)
                {
                    message = "站点名称与其他站点重复";
                    return false;
                }
                var longitude = Simple.DoubleConvertString(obj.longitude.ToString());
                var latitude = Simple.DoubleConvertString(obj.latitude.ToString());
                var elevation = Simple.DoubleConvertString(obj.elevation.ToString());
                var run = _mapRepository.Edit(site.Id.ToString(), CoordinateType.Project, longitude, latitude,
                    elevation);
                run += _repository.Update(site);
                if (run >= 2)
                    return true;
                message = "修改站点信息失败";
                return false;
            }
            catch (Exception e)
            {
                _logger.Error(e);
                message = e.Message;
                return false;
            }
        }

        /// <summary>
        /// 删除站点
        /// </summary>
        /// <param name="id"></param>
        /// <param name="exception"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public bool DeleteSite(string id, out string message)
        {
            message = "";
            try
            {
                var site = _repository.FindAll<Project>().Where(i => i.Id.ToString() == id.ToString()).ToArray();
                if (!site.Any())
                {
                    message = "站点不存在，无法删除";
                    return false;
                }
                if (_repository.Remove(site.First()) > 0)
                {
                    _mapRepository.DeleteTrue(site.First().Id.ToString());
                    return true;
                }
                message = "删除站点信息失败";
                return false;
            }
            catch (Exception e)
            {
                _logger.Error(e);
                message = e.Message;
                return false;
            }
        }

        #endregion

        #region 用户

        /// <summary>
        /// 添加用户信息
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="exception"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public bool AddUser(dynamic obj, out string message)
        {
            message = "";
            try
            {
                var siteid = obj.siteId.ToString();
                var staff = new User()
                {
                    Password = obj.password.ToString(),
                    PageLines = Simple.IntConvertString(obj.pageLines.ToString()),
                    Surname = obj.surname.ToString(),
                    RoleId = obj.roleId.ToString(),
                    Mobile = obj.mobile.ToString(),
                    SiteId = siteid,
                    RecordState = obj.status.ToString() == "正常" ? (int)RecordStateEnum.Normal : (int)RecordStateEnum.Deleted,
                    DistrictId = ""

                    //Memo = obj.remark.ToString()
                };
                if (_staffRepository.FindAll<User>().Count(s =>
                        String.Equals(s.Name, staff.Name, StringComparison.CurrentCultureIgnoreCase)) > 0)
                {
                    message = "用户登陆名重复";
                    _logger.Warn(message);
                    return false;
                }
                if (_repository.Add(staff) > 0) return true;
                message = "添加用户信息失败";
                _logger.Warn("IRepository Error 添加用户信息失败");
                return false;
            }
            catch (Exception e)
            {
                _logger.Error(e);
                message = e.Message;
                return false;
            }
        }

        /// <summary>
        /// 修改密码
        /// </summary>
        /// <param name="id"></param>
        /// <param name="obj"></param>
        /// <param name="exception"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public bool EditPassWord(string id, dynamic obj, out string message)
        {
            message = "";
            try
            {
                var users = Enumerable.Where<User>(_repository.FindAll<User>(),
                    i => i.Id.ToString() == id).ToList();
                if (!users.Any())
                {
                    message = "用户不存在，无法修改";
                    _logger.Warn(message);
                    return false;
                }
                var user = users.First();
                if (user.Password != obj.oldPassword.ToString())
                {
                    message = "密码不正确";
                    _logger.Warn(message);
                    return false;
                }
                user.Password = obj.newPassword.ToString();
                //user.ModifiedLog(user.Name, "修改密码");
                if (_repository.Update(user) > 0) return true;
                message = "修改用户密码失败";
                _logger.Warn(message);
                return false;
            }
            catch (Exception e)
            {
                _logger.Error(e);
                message = e.Message;
                return false;
            }
        }

        /// <summary>
        /// 密码验证
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="provingPass"></param>
        /// <returns></returns>
        public bool VerifyPassWord(string uid, string provingPass)
        {
            try
            {
                var operatorStaff = _repository.FindAllAsNoTracking<User>().First(s => s.Id.ToString() == uid);
                return operatorStaff.Password == provingPass;
            }
            catch (Exception e)
            {
                _logger.Error(e);
                throw;
            }
        }

        /// <summary>
        /// 初始化密码
        /// </summary>
        /// <param name="staffid"></param>
        /// <param name="password"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public bool InitialisePassWord(string staffid, out string password, out string message)
        {
            message = "";
            var staff = _repository.FindAll<User>().First(s => s.Id.ToString() == staffid);
            staff.Password = Simple.MakePassword(6);
            password = staff.Password;
            _repository.Update(staff);
            return true;
        }

        /// <summary>
        /// 获取密码
        /// </summary>
        /// <param name="staffid"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public string GetPassWord(string staffid, out string message)
        {
            message = "";
            var staff = _repository.FindAllAsNoTracking<User>().First(s => s.Id.ToString() == staffid);
            //TODO：后期会加密
            return staff.Password;
        }

        /// <summary>
        /// 修改用户信息
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public bool EditUser(dynamic obj, out string message)
        {
            message = "";
            try
            {
                var staffList = _staffRepository.FindAll<User>()
                    .Where(s => s.RecordState == (int)RecordStateEnum.Normal).ToList();
                var users = staffList.Where(i => i.Id.ToString() == obj.id.ToString()).ToList();
                var unusers = staffList.Where(s => s.Id.ToString() != obj.id.ToString()).ToList();
                if (!users.Any())
                {
                    message = "用户不存在，无法修改";
                    _logger.Warn(message);
                    return false;
                }
                //这个位置会出现异常  马贤辉发现 但没时间改 主要在熟悉流程 2019-8-29
                var user = users.First();
                if (user.Name.ToLower() == "admin" && user.Name == "admin")
                {
                    message = "不可以修改admin用户";
                    _logger.Warn(message);
                    return false;
                }
                //用户登陆名重复 也不应该 这个判断 应该注册的时候  或者 数据中 唯一主键
                if (unusers.Any(s => s.Name == obj.operatorName.ToString()))
                {
                    message = "用户登陆名重复";
                    _logger.Warn(message);
                    return false;
                }
                user.Name = obj.operatorName.ToString();
                user.Surname = obj.surname.ToString();
                user.Mobile = obj.mobile.ToString();
                user.PageLines = Simple.IntConvertString(obj.pageLines.ToString());
                user.RoleId = obj.roleId.ToString();
                user.SiteId = obj.siteId.ToString();
                user.RecordState = obj.status.ToString() == "正常" ? (int)RecordStateEnum.Normal : (int)RecordStateEnum.Deleted;
                user.DistrictId =
                    string.Join(",", JsonConvert.DeserializeObject<List<string>>(obj.district.ToString()));
                //user.Memo = obj.remark.ToString();

                if (_staffRepository.Update(user) > 0) return true;
                message = "修改用户信息失败";
                _logger.Warn(message);
                return false;
            }
            catch (Exception e)
            {
                _logger.Error(e);
                message = e.Message;
                return false;
            }
        }

        /// <summary>
        /// 获取用户行数
        /// </summary>
        /// <param name="staffId"></param>
        /// <returns></returns>
        public object SelectLines(string staffId)
        {
            try
            {
                //获取用户信息
                var staffEntities = Enumerable.Where<User>(_repository.FindAll<User>(),
                    s => s.Id.ToString() == staffId).ToList();
                if (staffEntities.Count == 0)
                {
                    throw new Exception("用户不存在");
                }
                return
                    new
                    {
                        showLines = staffEntities.First().PageLines
                    };
            }
            catch (Exception e)
            {
                _logger.Error(e);
                throw new Exception(e.Message);
            }
        }


        /// <summary>
        /// 修改用户行数
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="staffId"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public bool UpdateLines(dynamic obj, string staffId, out string message)
        {
            message = "";
            try
            {
                //获取用户信息
                var staffEntities = Enumerable.Where<User>(_repository.FindAll<User>(),
                    s => s.Id.ToString() == staffId).ToList();
                if (staffEntities.Count == 0)
                {
                    message = "用户不存在";
                    return false;
                }
                var staff = staffEntities.First();
                staff.PageLines = Simple.IntConvertString(obj.showLines.ToString());
                if (_repository.Update(staff) > 0)
                    return true;
                message = "修改密码失败";
                _logger.Warn(message);
                return false;
            }
            catch (Exception e)
            {
                _logger.Error(e);
                message = e.Message;
                return false;
            }
        }

        /// <summary>
        /// 删除用户信息
        /// </summary>
        /// <param name="id"></param>
        /// <param name="message"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public bool DeleteUser(string id, out string message)
        {
            message = "";
            try
            {
                if (Enumerable.Count<User>(_repository.FindAll<User>(),
                        r => r.Id.ToString() == id) == 0)
                {
                    message = "没有用户信息";
                    _logger.Warn(message);
                    return false;
                }
                var user = Enumerable.First<User>(_repository
                    .FindAll<User>(), r => r.Id.ToString() == id);
                if (user.Name == "admin")
                {
                    message = "无法删除系统管理员";
                    _logger.Warn(message);
                    return false;
                }
                if (_repository.Remove(user) > 0)
                    return true;
                message = "删除失败";
                _logger.Warn(message);
                return false;
            }
            catch (Exception e)
            {
                _logger.Error(e);
                message = e.Message;
                return false;
            }
        }

        #endregion
    }
}